package cn.zuo.view;

import cn.zuo.pojo.Message;
import cn.zuo.utils.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.math.BigInteger;
import java.net.Socket;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * @Author 白白旧维
 * @Date 2021/7/7 11:13
 */
public class ChatJFrame {
    private static final Logger logger = LoggerFactory.getLogger(ChatJFrame.class);//得到logger变量
    private Map<String,BigInteger> key;
    private JPanel mjp;
    private Jedis jedis = new Jedis("127.0.0.1",6379);
    private Lock lock = new ReentrantLock();

    public JPanel getMjp() {
        return mjp;
    }

    private JButton btn_send;
    private JTextArea allmsg;
    private JTextArea msg;
    private JTextField pathname;
    private JButton Button1;
    private JButton Button;
    private Socket s;
    private String sender;
    private String receiver;

    public Socket getS() {
        return s;
    }

    public void setS(Socket s) {
        this.s = s;
    }

    public ChatJFrame(String sender,String receiver,Socket s,Map<String,BigInteger> key) {
        this.sender = sender;
        this.receiver = receiver;
        this.key = key;
        this.s = s;

        //旧：发送公钥给另一个客户端
//        try {
//            ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
//            oos.writeObject(new Message(sender,receiver,key.get("e")+"_"+key.get("n"),"key"));
//
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        System.out.println("AES密钥库中:"+AESRandomKey.getSeed());

        if(RedisCtrl.isIsOpen()) {
            //读取缓存
            lock.lock();
            String redis_key = sender + "_" + receiver;
            String info_json = jedis.get(redis_key);
            System.out.println("读取缓存：" + info_json);

            List<String> infos = JSONArray.parseArray(info_json, String.class);
            if (infos != null) {
                for (String info :
                        infos) {
                    addMsg(new Message(receiver, sender, info));
                }
                System.out.println("addMsg完毕！");
                logger.info("addMsg完毕！");
            }
            lock.unlock();
        }

        btn_send.addActionListener(new ActionListener() {//发送信息
            @Override
            public void actionPerformed(ActionEvent e) {

                //info需要加密
                String info = "["+sender+"] 对 ["+receiver+"] 说: "+msg.getText().trim();//原信息
                if("".equals(info)){
                    return;
                }
                allmsg.append(info+"\n");

//                String info_hm = MD5.md5(info);//加哈希
                String info_hm = SHA256.sha256(info);//加哈希

                List<BigInteger> info_hm_signed = RSA.signed_mul(key.get("d"), key.get("n"), info_hm);//签名
                String info_hm_signed_json = JSON.toJSONString(info_hm_signed);

                String info_and_signed =info+"_"+info_hm_signed_json;//原信息和签名信息合并


                List<BigInteger> en_info_and_signed = RSA.encryption_mul(PublicKeyPool.getKey_e(receiver), PublicKeyPool.getKey_n(receiver), info_and_signed);
                String en_info_and_signed_json = JSON.toJSONString(en_info_and_signed);//加密信息

                //再使用AES对称加密算法，双重加密（如果加密解密速度太慢，就只使用对称加密）
                List<Byte> final_en_info = AES.encrypt_ECB(en_info_and_signed_json, AESRandomKey.getSeed());//使用ECB

                String final_en_info_json = JSON.toJSONString(final_en_info);
                byte[] final_en_info_bytes = new byte[final_en_info.size()];
                for(int i=0;i<final_en_info.size();i++){
                    final_en_info_bytes[i]=final_en_info.get(i);
                }

                //final_en_info_bytes是信息加密之后的byte数组
//                String final_en_info_json = new BigInteger(1, final_en_info_bytes).toString(16);


                Message message = new Message(sender,receiver,final_en_info_json,"chat");

                try {
                    ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
                    oos.writeObject(message);

                } catch (IOException ex) {
                    ex.printStackTrace();
                }finally {
                    msg.setText("");
                }


            }
        });
        Button1.addActionListener(new ActionListener() {//选择文件
            @Override
            public void actionPerformed(ActionEvent e) {

                JFileChooser ff = new JFileChooser("d://workplace");
                ff.setFileSelectionMode(JFileChooser.FILES_ONLY);

                int result = ff.showDialog(null, "请选择文件");

                if(result==JFileChooser.APPROVE_OPTION){
                    pathname.setText(ff.getSelectedFile().getPath());
                }

            }
        });
        Button.addActionListener(new ActionListener() {//发送文件
            @Override
            public void actionPerformed(ActionEvent e) {
                allmsg.append("["+sender+"] 给 ["+receiver+"] 发送文件：" + pathname.getText().trim()+"\n");

                //读取文件内容
                StringBuffer sb = new StringBuffer();//使用reader不适用中文文件读取

                try {
                    File file = new File(pathname.getText().trim());
//                    FileInputStream fis = new FileInputStream(file);
//                    BufferedInputStream bis = new BufferedInputStream(fis);
                    FileReader fr = new FileReader(file);
                    BufferedReader br = new BufferedReader(fr);


                    String str=null;
                    while((str=br.readLine())!=null){
                        sb.append(str+"\n");
                    }
//                    byte[] buffer = new byte[1024];
//                    int len=0;
//                    while((len=bis.read(buffer))!=-1){
//                        System.out.println(len);
//                    }

//                    System.out.println(new String(buffer));
                    String file_info = sb.toString();
//                    System.out.println(file_info);

                    //签名
//                    String file_info_hm = MD5.md5(file_info);
                    String file_info_hm = SHA256.sha256(file_info);

                    List<BigInteger> file_info_signed = RSA.signed_mul(key.get("d"), key.get("n"), file_info_hm);
                    String file_info_signed_json = JSON.toJSONString(file_info_signed);

                    String file_info_and_signed = file_info+"_"+file_info_signed_json;

                    //加密
                    List<Byte> en_file_info_and_signed = AES.encrypt_ECB(file_info_and_signed,AESRandomKey.getSeed());
                    String en_file_info_and_signed_json = JSON.toJSONString(en_file_info_and_signed);


                    Message msg = new Message(sender,receiver,en_file_info_and_signed_json,"file");
                    ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
                    oos.writeObject(msg);

                }catch (Exception ex){
                    ex.printStackTrace();
                }

            }
        });
    }

    public void addMsg(Message message){

        if("file".equals(message.getStatus())){//接收文件
            //解密
            String en_file_info_and_signed_json = message.getMsg();

            List<Byte> en_file_info_and_signed = JSONArray.parseArray(en_file_info_and_signed_json, Byte.class);

            String file_info_and_signed = AES.decrypt_ECB(en_file_info_and_signed, AESRandomKey.getSeed());

            String file_info = file_info_and_signed.split("_")[0];
//            System.out.println(file_info);
            String file_info_signed_json = file_info_and_signed.split("_")[1];


            //验证
//            String file_info_hm1 = MD5.md5(file_info);
            String file_info_hm1 = SHA256.sha256(file_info);

            List<BigInteger> info_hm_signed = JSONArray.parseArray(file_info_signed_json, BigInteger.class);

            String file_info_hm2 = RSA.verify_mul_hm(PublicKeyPool.getKey_e(receiver), PublicKeyPool.getKey_n(receiver), info_hm_signed);

            if(!file_info_hm1.equals(file_info_hm2)){
                System.out.println("签名不一致!!");
                logger.info("签名不一致！");
                return;
            }

            //文件保存到固定文件夹下
            String filename = UUID.randomUUID().toString();
            File file = new File("D:\\workplace\\target\\"+filename+".txt");
            FileWriter fw = null;
            try {
                fw = new FileWriter(file);
                BufferedWriter bw = new BufferedWriter(fw);

                bw.write(file_info);
                bw.flush();//写入文件一定要冲刷一下管道流！！！

            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    fw.close();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }



            //allmsg加信息
            allmsg.append("["+message.getSender()+"] 给 ["+message.getReceiver()+"] 发送文件，已保存到："+filename+".txt\n");

            return;
        }

//        System.out.println("2、addMsg："+message);
        //解密
//        String en_info_and_signed_json = message.getMsg();
        String final_en_info_json = message.getMsg();

        //先AES解密
        List<Byte> final_en_info = JSONArray.parseArray(final_en_info_json, Byte.class);
        String en_info_and_signed_json = AES.decrypt_ECB(final_en_info, AESRandomKey.getSeed());//使用ECB

//        System.out.println("4、"+en_info_and_signed_json);
        List<BigInteger> en_info_and_signed = JSONArray.parseArray(en_info_and_signed_json, BigInteger.class);
        String info_and_signed = RSA.decryption_mul(key.get("d"), key.get("n"), en_info_and_signed);//解密信息  //info错误原因主要是这里。。找到了，原来是使用的key不对
//        System.out.println("5、"+info_and_signed);

        String info = info_and_signed.split("_")[0];//原信息
//        System.out.println("6、"+info);
//        String info_hm1 = MD5.md5(info);//原信息哈希
        String info_hm1 = SHA256.sha256(info);//原信息哈希
//        System.out.println("7、"+info_hm1);

        String info_hm_signed_json = info_and_signed.split("_")[1];
//        System.out.println("8、"+info_hm_signed_json);
        List<BigInteger> info_hm_signed = JSONArray.parseArray(info_hm_signed_json, BigInteger.class);
        String info_hm2 = RSA.verify_mul_hm(PublicKeyPool.getKey_e(receiver), PublicKeyPool.getKey_n(receiver), info_hm_signed);//由签名获取的哈希
//        System.out.println("9、"+info_hm2);

        if(!info_hm1.equals(info_hm2)){//验证
            System.out.println("签名不一致!!");
            logger.info("签名不一致！");
            return;
        }

//        System.out.println("3、info："+info);//没有。。。主要问题

        this.allmsg.append(info+"\n");
    }




}
